package com.ljc.cjgl.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import org.abyss.data.specifications.Rule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ljc.cjgl.custom.TablePageable;
import com.ljc.cjgl.custom.TableResult;
import com.ljc.cjgl.entitiy.Marking;
import com.ljc.cjgl.entitiy.Scoring;
import com.ljc.cjgl.entitiy.ScoringGrade;
import com.ljc.cjgl.entitiy.Stu;
import com.ljc.cjgl.entitiy.TbClass;
import com.ljc.cjgl.entitiy.TbTest;
import com.ljc.cjgl.entitiy.Tea;
import com.ljc.cjgl.entitiy.TestRegister;
import com.ljc.cjgl.form.ScoringGradeForm;
import com.ljc.cjgl.security.UserUtils;
import com.ljc.cjgl.service.MarkingService;
import com.ljc.cjgl.service.ScoringGradeService;
import com.ljc.cjgl.service.ScoringService;
import com.ljc.cjgl.service.StudentService;
import com.ljc.cjgl.service.TestRegisterService;
import com.ljc.cjgl.service.TestService;

@Controller
@RequestMapping(value="/scoringGrade")
public class ScoringGradeController {
	@Autowired
	private ScoringGradeService service;
	@Autowired
	private TestRegisterService testRegisterService;
	@Autowired
	private ScoringService scoringService;
	@Autowired
	private UserUtils userUtils;
	@Autowired
	private MarkingService markingService;
	
	@RequestMapping("/manage")
	@PreAuthorize("hasRole('ROLE_TEACHER')")
	public String manage(ScoringGradeForm form,ModelMap map) {
		Integer gradingId=form.getGradingId();
		TestRegister tr=testRegisterService.findById(gradingId);
		form.setTestId(tr.getTest().getId());
		form.setStudentId(tr.getStudent().getId());
		Tea teacher=(Tea)userUtils.getUser(); 
		form.setTeacherId(teacher.getId());
		Specification<ScoringGrade> specification = buildSpec(form);
		List<ScoringGrade> list=service.findAll(specification);
		List<Scoring> scorings=scoringService.findByTestId(form.getTestId());
		service.checkRecord(list,scorings,teacher,tr.getStudent());
		map.put("model", form);
		return "scoringGrade/manage";
	}
	
	@RequestMapping(value="/manage2")
	@PreAuthorize("hasRole('ROLE_ADMIN')")
	public String manage2(ModelMap map) {
		List<TbTest> tests = testRegisterService.findDistinctTest();
		map.put("tests", tests);
		return "scoringGrade/manage2";
	}
	
	private Specification<ScoringGrade> buildSpec(ScoringGradeForm form){
		HashSet<Rule> rules=new HashSet<>();
		Integer testId = form.getTestId();
		if(testId!=null) {
			rules.add(Rule.property("scoring.test.id").equal(testId));
		}
		Integer studentId = form.getStudentId();
		if(studentId!=null) {
			rules.add(Rule.property("student.id").equal(studentId));
		}
		Integer teacherId = form.getTeacherId();
		if(teacherId!=null) {
			rules.add(Rule.property("teacher.id").equal(teacherId));
		}
		Integer classId = form.getClassId();
		if(classId!=null) {
			rules.add(Rule.property("student.tbClass.id").equal(classId));
		}
		String search = form.getSearch();
		if(StringUtils.hasText(search)) {
			HashSet<Rule> rules2=new HashSet<>();
			rules2.add(Rule.property("scoring.test.name").contain(search));
			rules2.add(Rule.property("student.name").like("%"+search+"%"));
			rules2.add(Rule.property("teacher.name").contain(search));
			rules2.add(Rule.property("scoring.title").contain(search));
			Rule rule = Rule.or(rules2);
			rules.add(rule);
		}
		return Rule.and(rules).toSpecification();
	}
	
	@RequestMapping(value="/page")
	@ResponseBody
	public Object page(TablePageable pageable,ScoringGradeForm form) {
		List<Order> orders=new ArrayList<>();
		orders.add(Order.asc("scoring.test.id"));
		orders.add(Order.asc("student.tbClass.id"));
		orders.add(Order.asc("teacher.id"));
		orders.add(Order.asc("student.id"));
		orders.add(Order.asc("scoring.id"));
		Sort sort=Sort.by(orders);
		PageRequest pageRequest = pageable.bulidPageable(sort);
		Specification<ScoringGrade> specification = buildSpec(form);
		Page<ScoringGrade> page = service.findAll(specification, pageRequest);
		return TableResult.bulidPageResult(page);
	}
	
	@RequestMapping(value="/gradeChange")
	@ResponseBody
	public Object gradeChange(Integer id,Integer grade) {
		HashMap<String, Object> result=service.gradeChange(id,grade);
		return result;
	}
	
	@RequestMapping(value="/testChange")
	@ResponseBody
	public Object testChange(Integer testId) {
		HashMap<String, Object> result=new HashMap<>();
		List<Marking> markings = markingService.findByTestId(testId);
		List<Tea> teachers=new ArrayList<>();
		for (Marking marking : markings) {
			teachers.add(marking.getTeacher());
		}
		result.put("teachers", teachers);
		List<TbClass> classes= testRegisterService.findTbClassByTestId(testId);
		result.put("classes",classes);
		List<Stu> students=testRegisterService.findStuByTestId(testId);
		result.put("students", students);
		return result;
	}
	
	@RequestMapping
	@ResponseBody
	public Object classChange(Integer testId,Integer classId) {
		List<Stu> students;
		if(testId!=null) {
			students= testRegisterService.findStuByTestId(testId);
		}else {
			students= testRegisterService.findDistinctStu();
		}
		for (Stu stu : students) {
			if(classId!=stu.getTbClass().getId()) {
				students.remove(stu);
			}
		}
		return students;
	}
}
